/*
 * mana (library)
 * Copyright (c) 2003 Shun Moriya <shun@mnu.sakura.ne.jp>
 *
 * The MIT License
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*!
 * @file
 * @brief	mana_stackクラスに関するヘッダーファイル
 *
 * このファイルはmana_stackクラスに関係するヘッダーファイルです。
 * mana_stackクラスはmana_actorクラスのスタック操作を行ないます。
 *
 * @author	Shun Moriya <shun@mnu.sakura.ne.jp>
 */

#if !defined(___MANA_STACK_H___)
#define ___MANA_STACK_H___

#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif

#if !defined(___MANA_STREAM_H___)
#include "mana_stream.h"
#endif
#include <stddef.h>

/*!
 * @brief	mana_stackクラス
 * mana_stackクラスはスタックを表しています。
 *
 * C++でいうところのメンバー変数ですが、C言語なので全てpublicになっています。
 * 操作用の関数を用意しているので、それらの関数を利用して操作してください。
 */
typedef struct mana_stack
{
	/*! @brief バッファ */
	union
	{
		const char** string_handle;	/*!< @brief 文字列ハンドル */
		void** void_handle;			/*!< @brief データハンドル */
		float* float_pointer;		/*!< @brief 実数ポインタ */
		int* integer_pointer;		/*!< @brief 整数ポインタ */
		void* void_pointer;			/*!< @brief データポインタ */
	}buffer;
	size_t allocated_size;			/*!< @brief 確保済みサイズ */
	size_t used_size;				/*!< @brief 使用済みサイズ(スタックポインタ) */
}mana_stack;

/*! @brief mana_stack オブジェクトの生成 */
extern mana_stack* mana_stack_create(void);

/*! @brief mana_stack オブジェクトの生成 */
extern mana_stack* mana_stack_create_with_size(const size_t size);

/*! @brief mana_stack オブジェクトの破棄 */
extern void mana_stack_destroy(mana_stack* self);

/*! @brief mana_stack オブジェクトのシリアライズ */
extern void mana_stack_serialize(const mana_stack* self, mana_stream* stream);

/*! @brief mana_stack オブジェクトのデシリアライズ */
extern void mana_stack_deserialize(mana_stack* self, mana_stream* stream);

/*! @brief mana_stack オブジェクトの初期化 */
extern void mana_stack_initialize(mana_stack* self);

/*! @brief mana_stack オブジェクトの初期化 */
extern void mana_stack_initialize_with_size(mana_stack* self, const size_t size);

/*! @brief mana_stack オブジェクトの開放 */
extern void mana_stack_finalize(mana_stack* self);

/*! @brief mana_stack オブジェクトのクリア */
extern void mana_stack_clear(mana_stack* self);

/*! @brief mana_stack オブジェクトのコピー */
extern void mana_stack_duplicate(mana_stack* self);

/*! @brief スタックポインタを移動 */
extern void mana_stack_remove(mana_stack* self, const size_t size);

/*! @brief 整数をプッシュ */
extern void mana_stack_push_integer(mana_stack* self, const int value);

/*! @brief 実数をプッシュ */
extern void mana_stack_push_real(mana_stack* self, const float value);

/*! @brief 文字列をプッシュ */
extern void mana_stack_push_string(mana_stack* self, const char* string);

/*! @brief ポインタをプッシュ */
extern void mana_stack_push_pointer(mana_stack* self, void* pointer);

/*! @brief データをプッシュ */
extern void mana_stack_push_data(mana_stack* self, const void* buffer, const size_t size);

/*! @brief 整数をポップ */
extern int mana_stack_pop_integer(mana_stack* self);

/*! @brief 実数をポップ */
extern float mana_stack_pop_real(mana_stack* self);

/*! @brief 文字列をポップ */
extern const char* mana_stack_pop_string(mana_stack* self);

/*! @brief ポインタをポップ */
extern void* mana_stack_pop_pointer(mana_stack* self);

/*! @brief アドレスをポップ */
extern void* mana_stack_pop_address(mana_stack* self);

/*! @brief データをポップ */
extern void mana_stack_pop_data(mana_stack* self, void* buffer, const size_t size);

/*! @brief 整数を取得 */
extern int mana_stack_get_integer(const mana_stack* self, const size_t index);

/*! @brief 実数を取得 */
extern float mana_stack_get_real(const mana_stack* self, const size_t index);

/*! @brief 文字列を取得 */
extern const char* mana_stack_get_string(const mana_stack* self, const size_t index);

/*! @brief ポインタを取得 */
extern void* mana_stack_get_pointer(const mana_stack* self, const size_t index);

/*! @brief アドレスを取得 */
extern void* mana_stack_get_address(const mana_stack* self, const size_t index);

/*! @brief 整数を設定 */
extern void mana_stack_set_integer(mana_stack* self, const size_t index, const int integer);

/*! @brief 実数を設定 */
extern void mana_stack_set_real(mana_stack* self, const size_t index, const float real);

/*! @brief 文字列を設定 */
extern void mana_stack_set_string(mana_stack* self, const size_t index, const char* string);

/*! @brief ポインタを設定 */
extern void mana_stack_set_pointer(mana_stack* self, const size_t index, void* pointer);

/*! @brief スタックのサイズを取得 */
extern size_t mana_stack_get_size(const mana_stack* self);

/*! @brief スタックのサイズを設定 */
extern void mana_stack_set_size(mana_stack* self, const size_t size);

/*! @brief スタックを比較 */
extern int mana_stack_compare(const mana_stack* self, const mana_stack* other);

#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) || defined(c_plusplus)
}
#endif

#endif
